/*!
 * \file LMDBKeys.h
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader高级数据存储系统LMDB键定义文件
 * 
 * \details 该文件定义了LMDB（Lightning Memory-Mapped Database）数据库中使用的键结构，包括：
 *          - 字节序转换工具函数
 *          - HFT（高频交易）数据键结构
 *          - K线数据键结构
 *          - 内存对齐优化
 *          
 *          LMDB是一个高性能的嵌入式数据库，适用于高频数据存储。
 *          键结构的设计直接影响数据库的查询性能和存储效率。
 */

#pragma once
#include <stdint.h>
#include <string.h>
#include "../Includes/WTSMarcos.h"

/*!
 * \brief 16位整数字节序转换函数
 * \param src 源16位整数
 * \return 转换后的16位整数
 * 
 * 将16位整数的字节序进行反转，用于处理大小端字节序兼容性问题。
 * 这在跨平台数据存储中非常重要，确保数据在不同架构系统间的一致性。
 */
static uint16_t reverseEndian(uint16_t src)
{
	uint16_t up = (src & 0x00FF) << 8;		// 取低8位，左移8位
	uint16_t low = (src & 0xFF00) >> 8;		// 取高8位，右移8位
	return up + low;
}

/*!
 * \brief 32位整数字节序转换函数
 * \param src 源32位整数
 * \return 转换后的32位整数
 * 
 * 将32位整数的字节序进行反转，实现大小端转换。
 * 通过位运算将4个字节的顺序完全颠倒。
 */
static uint32_t reverseEndian(uint32_t src)
{
	uint32_t x = (src & 0x000000FF) << 24;	// 最低字节移到最高位
	uint32_t y = (src & 0x0000FF00) << 8;	// 次低字节移到次高位
	uint32_t z = (src & 0x00FF0000) >> 8;	// 次高字节移到次低位
	uint32_t w = (src & 0xFF000000) >> 24;	// 最高字节移到最低位
	return x + y + z + w;
}

#pragma pack(push, 1)  ///< 设置1字节对齐，确保结构体紧密排列，优化LMDB键的存储效率

/*!
 * \struct _LMDBHftKey
 * \brief LMDB高频交易数据键结构体
 * 
 * \details 用于LMDB数据库中高频交易数据的键定义，包含：
 *          - 交易所代码：标识数据来源的交易所
 *          - 合约代码：标识具体的交易合约
 *          - 日期：交易日期
 *          - 时间：具体时间点
 *          
 *          该结构专为高频数据设计，支持按时间序列快速检索。
 *          所有数值字段都经过字节序转换，确保数据库的排序正确性。
 */
typedef struct _LMDBHftKey
{
	char		_exchg[MAX_EXCHANGE_LENGTH];	///< 交易所代码（如SSE、SZSE、SHFE等）
	char		_code[MAX_INSTRUMENT_LENGTH];	///< 合约代码（如600000、IF2012等）
	uint32_t	_date;							///< 交易日期（YYYYMMDD格式，字节序已转换）
	uint32_t	_time;							///< 交易时间（HHMMSSsss格式，字节序已转换）

	/*!
	 * \brief 构造函数
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \param date 交易日期
	 * \param time 交易时间
	 * 
	 * 初始化HFT数据键，自动处理字节序转换以确保数据库排序的正确性
	 */
	_LMDBHftKey(const char* exchg, const char* code, uint32_t date, uint32_t time)
	{
		memset(this, 0, sizeof(_LMDBHftKey));	// 清零整个结构体
		strcpy(_exchg, exchg);					// 复制交易所代码
		strcpy(_code, code);					// 复制合约代码
		_date = reverseEndian(date);			// 转换日期字节序
		_time = reverseEndian(time);			// 转换时间字节序
	}
} LMDBHftKey;

/*!
 * \struct _LMDBBarKey
 * \brief LMDB K线数据键结构体
 * 
 * \details 用于LMDB数据库中K线数据的键定义，包含：
 *          - 交易所代码：标识数据来源的交易所
 *          - 合约代码：标识具体的交易合约
 *          - K线时间：K线周期的时间戳
 *          
 *          该结构专为K线数据设计，支持按时间周期快速检索。
 *          时间字段经过字节序转换，确保时间序列的正确排序。
 */
typedef struct  _LMDBBarKey
{
public:
	char		_exchg[MAX_EXCHANGE_LENGTH];	///< 交易所代码（如SSE、SZSE、SHFE等）
	char		_code[MAX_INSTRUMENT_LENGTH];	///< 合约代码（如600000、IF2012等）
	uint32_t	_bartime;						///< K线时间戳（字节序已转换）

	/*!
	 * \brief 构造函数
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \param bartime K线时间戳
	 * 
	 * 初始化K线数据键，自动处理字节序转换以确保数据库排序的正确性
	 */
	_LMDBBarKey(const char* exchg, const char* code, uint32_t bartime)
	{
		memset(this, 0, sizeof(_LMDBBarKey));	// 清零整个结构体
		strcpy(_exchg, exchg);					// 复制交易所代码
		strcpy(_code, code);					// 复制合约代码
		_bartime = reverseEndian(bartime);		// 转换时间字节序
	}
} LMDBBarKey;

#pragma pack(pop)  ///< 恢复默认结构体对齐方式